Passed
Push — master ( 445067...6ce435 )
by Johan
02:18
created

ImportFinder   F

Complexity

Total Complexity 272

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 272
eloc 60
dl 0
loc 78
rs 2
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like ImportFinder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
Object.defineProperty(exports, "__esModule", { value: true });
3
const ts = require("typescript");
4
const node_1 = require("../typeguard/node");
5
const _3_2_1 = require("../typeguard/3.2");
6
const type_1 = require("./type");
7
function getChildOfKind(node, kind, sourceFile) {
8
    for (const child of node.getChildren(sourceFile))
9
        if (child.kind === kind)
10
            return child;
11
}
12
exports.getChildOfKind = getChildOfKind;
13
function isTokenKind(kind) {
14
    return kind >= ts.SyntaxKind.FirstToken && kind <= ts.SyntaxKind.LastToken;
15
}
16
exports.isTokenKind = isTokenKind;
17
function isNodeKind(kind) {
18
    return kind >= ts.SyntaxKind.FirstNode;
19
}
20
exports.isNodeKind = isNodeKind;
21
function isAssignmentKind(kind) {
22
    return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
23
}
24
exports.isAssignmentKind = isAssignmentKind;
25
function isTypeNodeKind(kind) {
26
    return kind >= ts.SyntaxKind.FirstTypeNode && kind <= ts.SyntaxKind.LastTypeNode;
27
}
28
exports.isTypeNodeKind = isTypeNodeKind;
29
function isJsDocKind(kind) {
30
    return kind >= ts.SyntaxKind.FirstJSDocNode && kind <= ts.SyntaxKind.LastJSDocNode;
31
}
32
exports.isJsDocKind = isJsDocKind;
33
function isKeywordKind(kind) {
34
    return kind >= ts.SyntaxKind.FirstKeyword && kind <= ts.SyntaxKind.LastKeyword;
35
}
36
exports.isKeywordKind = isKeywordKind;
37
function isThisParameter(parameter) {
38
    return parameter.name.kind === ts.SyntaxKind.Identifier && parameter.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword;
39
}
40
exports.isThisParameter = isThisParameter;
41
function getModifier(node, kind) {
42
    if (node.modifiers !== undefined)
43
        for (const modifier of node.modifiers)
44
            if (modifier.kind === kind)
45
                return modifier;
46
}
47
exports.getModifier = getModifier;
48
function hasModifier(modifiers, ...kinds) {
49
    if (modifiers === undefined)
50
        return false;
51
    for (const modifier of modifiers)
52
        if (kinds.includes(modifier.kind))
53
            return true;
54
    return false;
55
}
56
exports.hasModifier = hasModifier;
57
function isParameterProperty(node) {
58
    return hasModifier(node.modifiers, ts.SyntaxKind.PublicKeyword, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword, ts.SyntaxKind.ReadonlyKeyword);
59
}
60
exports.isParameterProperty = isParameterProperty;
61
function hasAccessModifier(node) {
62
    return hasModifier(node.modifiers, ts.SyntaxKind.PublicKeyword, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword);
63
}
64
exports.hasAccessModifier = hasAccessModifier;
65
function isFlagSet(obj, flag) {
66
    return (obj.flags & flag) !== 0;
67
}
68
exports.isNodeFlagSet = isFlagSet;
69
exports.isTypeFlagSet = isFlagSet;
70
exports.isSymbolFlagSet = isFlagSet;
71
function isObjectFlagSet(objectType, flag) {
72
    return (objectType.objectFlags & flag) !== 0;
73
}
74
exports.isObjectFlagSet = isObjectFlagSet;
75
function isModifierFlagSet(node, flag) {
76
    return (ts.getCombinedModifierFlags(node) & flag) !== 0;
77
}
78
exports.isModifierFlagSet = isModifierFlagSet;
79
function getPreviousStatement(statement) {
80
    const parent = statement.parent;
81
    if (node_1.isBlockLike(parent)) {
82
        const index = parent.statements.indexOf(statement);
83
        if (index > 0)
84
            return parent.statements[index - 1];
85
    }
86
}
87
exports.getPreviousStatement = getPreviousStatement;
88
function getNextStatement(statement) {
89
    const parent = statement.parent;
90
    if (node_1.isBlockLike(parent)) {
91
        const index = parent.statements.indexOf(statement);
92
        if (index < parent.statements.length)
93
            return parent.statements[index + 1];
94
    }
95
}
96
exports.getNextStatement = getNextStatement;
97
function getPreviousToken(node, sourceFile) {
98
    let parent = node.parent;
99
    while (parent !== undefined && parent.pos === node.pos)
100
        parent = parent.parent;
101
    if (parent === undefined)
102
        return;
103
    outer: while (true) {
104
        const children = parent.getChildren(sourceFile);
105
        for (let i = children.length - 1; i >= 0; --i) {
106
            const child = children[i];
107
            if (child.pos < node.pos && child.kind !== ts.SyntaxKind.JSDocComment) {
108
                if (isTokenKind(child.kind))
109
                    return child;
110
                parent = child;
111
                continue outer;
112
            }
113
        }
114
        return;
115
    }
116
}
117
exports.getPreviousToken = getPreviousToken;
118
function getNextToken(node, sourceFile = node.getSourceFile()) {
119
    if (node.kind === ts.SyntaxKind.SourceFile || node.kind === ts.SyntaxKind.EndOfFileToken)
120
        return;
121
    const end = node.end;
122
    node = node.parent;
123
    while (node.end === end) {
124
        if (node.parent === undefined)
125
            return node.endOfFileToken;
126
        node = node.parent;
127
    }
128
    return getTokenAtPositionWorker(node, end, sourceFile, false);
129
}
130
exports.getNextToken = getNextToken;
131
function getTokenAtPosition(parent, pos, sourceFile, allowJsDoc) {
132
    if (pos < parent.pos || pos >= parent.end)
133
        return;
134
    if (isTokenKind(parent.kind))
135
        return parent;
136
    if (sourceFile === undefined)
137
        sourceFile = parent.getSourceFile();
138
    return getTokenAtPositionWorker(parent, pos, sourceFile, allowJsDoc === true);
139
}
140
exports.getTokenAtPosition = getTokenAtPosition;
141
function getTokenAtPositionWorker(node, pos, sourceFile, allowJsDoc) {
142
    outer: while (true) {
143
        for (const child of node.getChildren(sourceFile)) {
144
            if (child.end > pos && (allowJsDoc || child.kind !== ts.SyntaxKind.JSDocComment)) {
145
                if (isTokenKind(child.kind))
146
                    return child;
147
                node = child;
148
                continue outer;
149
            }
150
        }
151
        return;
152
    }
153
}
154
function getCommentAtPosition(sourceFile, pos, parent = sourceFile) {
155
    const token = getTokenAtPosition(parent, pos, sourceFile);
156
    if (token === undefined || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || '').length)
157
        return;
158
    const startPos = token.pos === 0
159
        ? (ts.getShebang(sourceFile.text) || '').length
160
        : token.pos;
161
    return startPos !== 0 && ts.forEachTrailingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos) ||
162
        ts.forEachLeadingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos);
163
}
164
exports.getCommentAtPosition = getCommentAtPosition;
165
function commentAtPositionCallback(pos, end, kind, _nl, at) {
166
    return at >= pos && at < end ? { pos, end, kind } : undefined;
167
}
168
function isPositionInComment(sourceFile, pos, parent) {
169
    return getCommentAtPosition(sourceFile, pos, parent) !== undefined;
170
}
171
exports.isPositionInComment = isPositionInComment;
172
function commentText(sourceText, comment) {
173
    return sourceText.substring(comment.pos + 2, comment.kind === ts.SyntaxKind.SingleLineCommentTrivia ? comment.end : comment.end - 2);
174
}
175
exports.commentText = commentText;
176
function getWrappedNodeAtPosition(wrap, pos) {
177
    if (wrap.node.pos > pos || wrap.node.end <= pos)
178
        return;
179
    outer: while (true) {
180
        for (const child of wrap.children) {
181
            if (child.node.pos > pos)
182
                return wrap;
183
            if (child.node.end > pos) {
184
                wrap = child;
185
                continue outer;
186
            }
187
        }
188
        return wrap;
189
    }
190
}
191
exports.getWrappedNodeAtPosition = getWrappedNodeAtPosition;
192
function getPropertyName(propertyName) {
193
    if (propertyName.kind === ts.SyntaxKind.ComputedPropertyName) {
194
        if (!node_1.isLiteralExpression(propertyName.expression))
195
            return;
196
        if (_3_2_1.isBigIntLiteral(propertyName.expression))
197
            return propertyName.expression.text.slice(0, -1);
198
        return propertyName.expression.text;
199
    }
200
    return propertyName.text;
201
}
202
exports.getPropertyName = getPropertyName;
203
function forEachDestructuringIdentifier(pattern, fn) {
204
    for (const element of pattern.elements) {
205
        if (element.kind !== ts.SyntaxKind.BindingElement)
206
            continue;
207
        let result;
208
        if (element.name.kind === ts.SyntaxKind.Identifier) {
209
            result = fn(element);
210
        }
211
        else {
212
            result = forEachDestructuringIdentifier(element.name, fn);
213
        }
214
        if (result)
215
            return result;
216
    }
217
}
218
exports.forEachDestructuringIdentifier = forEachDestructuringIdentifier;
219
function forEachDeclaredVariable(declarationList, cb) {
220
    for (const declaration of declarationList.declarations) {
221
        let result;
222
        if (declaration.name.kind === ts.SyntaxKind.Identifier) {
223
            result = cb(declaration);
224
        }
225
        else {
226
            result = forEachDestructuringIdentifier(declaration.name, cb);
227
        }
228
        if (result)
229
            return result;
230
    }
231
}
232
exports.forEachDeclaredVariable = forEachDeclaredVariable;
233
var VariableDeclarationKind;
234
(function (VariableDeclarationKind) {
235
    VariableDeclarationKind[VariableDeclarationKind["Var"] = 0] = "Var";
236
    VariableDeclarationKind[VariableDeclarationKind["Let"] = 1] = "Let";
237
    VariableDeclarationKind[VariableDeclarationKind["Const"] = 2] = "Const";
238
})(VariableDeclarationKind = exports.VariableDeclarationKind || (exports.VariableDeclarationKind = {}));
239
function getVariableDeclarationKind(declarationList) {
240
    if (declarationList.flags & ts.NodeFlags.Let)
241
        return 1;
242
    if (declarationList.flags & ts.NodeFlags.Const)
243
        return 2;
244
    return 0;
245
}
246
exports.getVariableDeclarationKind = getVariableDeclarationKind;
247
function isBlockScopedVariableDeclarationList(declarationList) {
248
    return (declarationList.flags & ts.NodeFlags.BlockScoped) !== 0;
249
}
250
exports.isBlockScopedVariableDeclarationList = isBlockScopedVariableDeclarationList;
251
function isBlockScopedVariableDeclaration(declaration) {
252
    const parent = declaration.parent;
253
    return parent.kind === ts.SyntaxKind.CatchClause ||
254
        isBlockScopedVariableDeclarationList(parent);
255
}
256
exports.isBlockScopedVariableDeclaration = isBlockScopedVariableDeclaration;
257
function isBlockScopedDeclarationStatement(statement) {
258
    switch (statement.kind) {
259
        case ts.SyntaxKind.VariableStatement:
260
            return isBlockScopedVariableDeclarationList(statement.declarationList);
261
        case ts.SyntaxKind.ClassDeclaration:
262
        case ts.SyntaxKind.EnumDeclaration:
263
        case ts.SyntaxKind.InterfaceDeclaration:
264
        case ts.SyntaxKind.TypeAliasDeclaration:
265
            return true;
266
        default:
267
            return false;
268
    }
269
}
270
exports.isBlockScopedDeclarationStatement = isBlockScopedDeclarationStatement;
271
function isInSingleStatementContext(statement) {
272
    switch (statement.parent.kind) {
273
        case ts.SyntaxKind.ForStatement:
274
        case ts.SyntaxKind.ForInStatement:
275
        case ts.SyntaxKind.ForOfStatement:
276
        case ts.SyntaxKind.WhileStatement:
277
        case ts.SyntaxKind.DoStatement:
278
        case ts.SyntaxKind.IfStatement:
279
        case ts.SyntaxKind.WithStatement:
280
        case ts.SyntaxKind.LabeledStatement:
281
            return true;
282
        default:
283
            return false;
284
    }
285
}
286
exports.isInSingleStatementContext = isInSingleStatementContext;
287
var ScopeBoundary;
288
(function (ScopeBoundary) {
289
    ScopeBoundary[ScopeBoundary["None"] = 0] = "None";
290
    ScopeBoundary[ScopeBoundary["Function"] = 1] = "Function";
291
    ScopeBoundary[ScopeBoundary["Block"] = 2] = "Block";
292
    ScopeBoundary[ScopeBoundary["Type"] = 4] = "Type";
293
    ScopeBoundary[ScopeBoundary["ConditionalType"] = 8] = "ConditionalType";
294
})(ScopeBoundary = exports.ScopeBoundary || (exports.ScopeBoundary = {}));
295
var ScopeBoundarySelector;
296
(function (ScopeBoundarySelector) {
297
    ScopeBoundarySelector[ScopeBoundarySelector["Function"] = 1] = "Function";
298
    ScopeBoundarySelector[ScopeBoundarySelector["Block"] = 3] = "Block";
299
    ScopeBoundarySelector[ScopeBoundarySelector["Type"] = 7] = "Type";
300
    ScopeBoundarySelector[ScopeBoundarySelector["InferType"] = 8] = "InferType";
301
})(ScopeBoundarySelector = exports.ScopeBoundarySelector || (exports.ScopeBoundarySelector = {}));
302
function isScopeBoundary(node) {
303
    return isFunctionScopeBoundary(node) || isBlockScopeBoundary(node) || isTypeScopeBoundary(node);
304
}
305
exports.isScopeBoundary = isScopeBoundary;
306
function isTypeScopeBoundary(node) {
307
    switch (node.kind) {
308
        case ts.SyntaxKind.InterfaceDeclaration:
309
        case ts.SyntaxKind.TypeAliasDeclaration:
310
        case ts.SyntaxKind.MappedType:
311
            return 4;
312
        case ts.SyntaxKind.ConditionalType:
313
            return 8;
314
        default:
315
            return 0;
316
    }
317
}
318
exports.isTypeScopeBoundary = isTypeScopeBoundary;
319
function isFunctionScopeBoundary(node) {
320
    switch (node.kind) {
321
        case ts.SyntaxKind.FunctionExpression:
322
        case ts.SyntaxKind.ArrowFunction:
323
        case ts.SyntaxKind.Constructor:
324
        case ts.SyntaxKind.ModuleDeclaration:
325
        case ts.SyntaxKind.ClassDeclaration:
326
        case ts.SyntaxKind.ClassExpression:
327
        case ts.SyntaxKind.EnumDeclaration:
328
        case ts.SyntaxKind.MethodDeclaration:
329
        case ts.SyntaxKind.FunctionDeclaration:
330
        case ts.SyntaxKind.GetAccessor:
331
        case ts.SyntaxKind.SetAccessor:
332
        case ts.SyntaxKind.MethodSignature:
333
        case ts.SyntaxKind.CallSignature:
334
        case ts.SyntaxKind.ConstructSignature:
335
        case ts.SyntaxKind.ConstructorType:
336
        case ts.SyntaxKind.FunctionType:
337
            return 1;
338
        case ts.SyntaxKind.SourceFile:
339
            return ts.isExternalModule(node) ? 1 : 0;
340
        default:
341
            return 0;
342
    }
343
}
344
exports.isFunctionScopeBoundary = isFunctionScopeBoundary;
345
function isBlockScopeBoundary(node) {
346
    switch (node.kind) {
347
        case ts.SyntaxKind.Block:
348
            const parent = node.parent;
349
            return parent.kind !== ts.SyntaxKind.CatchClause &&
350
                (parent.kind === ts.SyntaxKind.SourceFile ||
351
                    !isFunctionScopeBoundary(parent))
352
                ? 2
353
                : 0;
354
        case ts.SyntaxKind.ForStatement:
355
        case ts.SyntaxKind.ForInStatement:
356
        case ts.SyntaxKind.ForOfStatement:
357
        case ts.SyntaxKind.CaseBlock:
358
        case ts.SyntaxKind.CatchClause:
359
        case ts.SyntaxKind.WithStatement:
360
            return 2;
361
        default:
362
            return 0;
363
    }
364
}
365
exports.isBlockScopeBoundary = isBlockScopeBoundary;
366
function hasOwnThisReference(node) {
367
    switch (node.kind) {
368
        case ts.SyntaxKind.ClassDeclaration:
369
        case ts.SyntaxKind.ClassExpression:
370
        case ts.SyntaxKind.FunctionExpression:
371
            return true;
372
        case ts.SyntaxKind.FunctionDeclaration:
373
            return node.body !== undefined;
374
        case ts.SyntaxKind.MethodDeclaration:
375
        case ts.SyntaxKind.GetAccessor:
376
        case ts.SyntaxKind.SetAccessor:
377
            return node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression;
378
        default:
379
            return false;
380
    }
381
}
382
exports.hasOwnThisReference = hasOwnThisReference;
383
function isFunctionWithBody(node) {
384
    switch (node.kind) {
385
        case ts.SyntaxKind.GetAccessor:
386
        case ts.SyntaxKind.SetAccessor:
387
        case ts.SyntaxKind.FunctionDeclaration:
388
        case ts.SyntaxKind.MethodDeclaration:
389
        case ts.SyntaxKind.Constructor:
390
            return node.body !== undefined;
391
        case ts.SyntaxKind.FunctionExpression:
392
        case ts.SyntaxKind.ArrowFunction:
393
            return true;
394
        default:
395
            return false;
396
    }
397
}
398
exports.isFunctionWithBody = isFunctionWithBody;
399
function forEachToken(node, cb, sourceFile = node.getSourceFile()) {
400
    return (function iterate(child) {
401
        if (isTokenKind(child.kind))
402
            return cb(child);
403
        if (child.kind !== ts.SyntaxKind.JSDocComment)
404
            return child.getChildren(sourceFile).forEach(iterate);
405
    })(node);
406
}
407
exports.forEachToken = forEachToken;
408
function forEachTokenWithTrivia(node, cb, sourceFile = node.getSourceFile()) {
409
    const fullText = sourceFile.text;
410
    const scanner = ts.createScanner(sourceFile.languageVersion, false, sourceFile.languageVariant, fullText);
411
    return forEachToken(node, (token) => {
412
        const tokenStart = token.kind === ts.SyntaxKind.JsxText || token.pos === token.end ? token.pos : token.getStart(sourceFile);
413
        if (tokenStart !== token.pos) {
414
            scanner.setTextPos(token.pos);
415
            let kind = scanner.scan();
416
            let pos = scanner.getTokenPos();
417
            while (pos < tokenStart) {
418
                const textPos = scanner.getTextPos();
419
                cb(fullText, kind, { pos, end: textPos }, token.parent);
420
                if (textPos === tokenStart)
421
                    break;
422
                kind = scanner.scan();
423
                pos = scanner.getTokenPos();
424
            }
425
        }
426
        return cb(fullText, token.kind, { end: token.end, pos: tokenStart }, token.parent);
427
    }, sourceFile);
428
}
429
exports.forEachTokenWithTrivia = forEachTokenWithTrivia;
430
function forEachComment(node, cb, sourceFile = node.getSourceFile()) {
431
    const fullText = sourceFile.text;
432
    const notJsx = sourceFile.languageVariant !== ts.LanguageVariant.JSX;
433
    return forEachToken(node, (token) => {
434
        if (token.pos === token.end)
435
            return;
436
        if (token.kind !== ts.SyntaxKind.JsxText)
437
            ts.forEachLeadingCommentRange(fullText, token.pos === 0 ? (ts.getShebang(fullText) || '').length : token.pos, commentCallback);
438
        if (notJsx || canHaveTrailingTrivia(token))
439
            return ts.forEachTrailingCommentRange(fullText, token.end, commentCallback);
440
    }, sourceFile);
441
    function commentCallback(pos, end, kind) {
442
        cb(fullText, { pos, end, kind });
443
    }
444
}
445
exports.forEachComment = forEachComment;
446
function canHaveTrailingTrivia(token) {
447
    switch (token.kind) {
448
        case ts.SyntaxKind.CloseBraceToken:
449
            return token.parent.kind !== ts.SyntaxKind.JsxExpression || !isJsxElementOrFragment(token.parent.parent);
450
        case ts.SyntaxKind.GreaterThanToken:
451
            switch (token.parent.kind) {
452
                case ts.SyntaxKind.JsxOpeningElement:
453
                    return token.end !== token.parent.end;
454
                case ts.SyntaxKind.JsxOpeningFragment:
455
                    return false;
456
                case ts.SyntaxKind.JsxSelfClosingElement:
457
                    return token.end !== token.parent.end ||
458
                        !isJsxElementOrFragment(token.parent.parent);
459
                case ts.SyntaxKind.JsxClosingElement:
460
                case ts.SyntaxKind.JsxClosingFragment:
461
                    return !isJsxElementOrFragment(token.parent.parent.parent);
462
            }
463
    }
464
    return true;
465
}
466
function isJsxElementOrFragment(node) {
467
    return node.kind === ts.SyntaxKind.JsxElement || node.kind === ts.SyntaxKind.JsxFragment;
468
}
469
function getLineRanges(sourceFile) {
470
    const lineStarts = sourceFile.getLineStarts();
471
    const result = [];
472
    const length = lineStarts.length;
473
    const sourceText = sourceFile.text;
474
    let pos = 0;
475
    for (let i = 1; i < length; ++i) {
476
        const end = lineStarts[i];
477
        let lineEnd = end;
478
        for (; lineEnd > pos; --lineEnd)
479
            if (!ts.isLineBreak(sourceText.charCodeAt(lineEnd - 1)))
480
                break;
481
        result.push({
482
            pos,
483
            end,
484
            contentLength: lineEnd - pos,
485
        });
486
        pos = end;
487
    }
488
    result.push({
489
        pos,
490
        end: sourceFile.end,
491
        contentLength: sourceFile.end - pos,
492
    });
493
    return result;
494
}
495
exports.getLineRanges = getLineRanges;
496
function getLineBreakStyle(sourceFile) {
497
    const lineStarts = sourceFile.getLineStarts();
498
    return lineStarts.length === 1 || lineStarts[1] < 2 || sourceFile.text[lineStarts[1] - 2] !== '\r'
499
        ? '\n'
500
        : '\r\n';
501
}
502
exports.getLineBreakStyle = getLineBreakStyle;
503
let cachedScanner;
504
function scanToken(text, languageVersion) {
505
    if (cachedScanner === undefined) {
506
        cachedScanner = ts.createScanner(languageVersion, false, undefined, text);
507
    }
508
    else {
509
        cachedScanner.setScriptTarget(languageVersion);
510
        cachedScanner.setText(text);
511
    }
512
    cachedScanner.scan();
513
    return cachedScanner;
514
}
515
function isValidIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
516
    const scan = scanToken(text, languageVersion);
517
    return scan.isIdentifier() && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
518
}
519
exports.isValidIdentifier = isValidIdentifier;
520
function charSize(ch) {
521
    return ch >= 0x10000 ? 2 : 1;
522
}
523
function isValidPropertyAccess(text, languageVersion = ts.ScriptTarget.Latest) {
524
    if (text.length === 0)
525
        return false;
526
    let ch = text.codePointAt(0);
527
    if (!ts.isIdentifierStart(ch, languageVersion))
528
        return false;
529
    for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
530
        ch = text.codePointAt(i);
531
        if (!ts.isIdentifierPart(ch, languageVersion))
532
            return false;
533
    }
534
    return true;
535
}
536
exports.isValidPropertyAccess = isValidPropertyAccess;
537
function isValidPropertyName(text, languageVersion = ts.ScriptTarget.Latest) {
538
    if (isValidPropertyAccess(text, languageVersion))
539
        return true;
540
    const scan = scanToken(text, languageVersion);
541
    return scan.getTextPos() === text.length &&
542
        scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTokenValue() === text;
543
}
544
exports.isValidPropertyName = isValidPropertyName;
545
function isValidNumericLiteral(text, languageVersion = ts.ScriptTarget.Latest) {
546
    const scan = scanToken(text, languageVersion);
547
    return scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
548
}
549
exports.isValidNumericLiteral = isValidNumericLiteral;
550
function isValidJsxIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
551
    if (text.length === 0)
552
        return false;
553
    let ch = text.codePointAt(0);
554
    if (!ts.isIdentifierStart(ch, languageVersion))
555
        return false;
556
    for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
557
        ch = text.codePointAt(i);
558
        if (!ts.isIdentifierPart(ch, languageVersion) && ch !== 45)
559
            return false;
560
    }
561
    return true;
562
}
563
exports.isValidJsxIdentifier = isValidJsxIdentifier;
564
function isNumericPropertyName(name) {
565
    return String(+name) === name;
566
}
567
exports.isNumericPropertyName = isNumericPropertyName;
568
function isSameLine(sourceFile, pos1, pos2) {
569
    return ts.getLineAndCharacterOfPosition(sourceFile, pos1).line === ts.getLineAndCharacterOfPosition(sourceFile, pos2).line;
570
}
571
exports.isSameLine = isSameLine;
572
var SideEffectOptions;
573
(function (SideEffectOptions) {
574
    SideEffectOptions[SideEffectOptions["None"] = 0] = "None";
575
    SideEffectOptions[SideEffectOptions["TaggedTemplate"] = 1] = "TaggedTemplate";
576
    SideEffectOptions[SideEffectOptions["Constructor"] = 2] = "Constructor";
577
    SideEffectOptions[SideEffectOptions["JsxElement"] = 4] = "JsxElement";
578
})(SideEffectOptions = exports.SideEffectOptions || (exports.SideEffectOptions = {}));
579
function hasSideEffects(node, options) {
580
    switch (node.kind) {
581
        case ts.SyntaxKind.CallExpression:
582
        case ts.SyntaxKind.PostfixUnaryExpression:
583
        case ts.SyntaxKind.AwaitExpression:
584
        case ts.SyntaxKind.YieldExpression:
585
        case ts.SyntaxKind.DeleteExpression:
586
            return true;
587
        case ts.SyntaxKind.TypeAssertionExpression:
588
        case ts.SyntaxKind.AsExpression:
589
        case ts.SyntaxKind.ParenthesizedExpression:
590
        case ts.SyntaxKind.NonNullExpression:
591
        case ts.SyntaxKind.VoidExpression:
592
        case ts.SyntaxKind.TypeOfExpression:
593
        case ts.SyntaxKind.PropertyAccessExpression:
594
        case ts.SyntaxKind.SpreadElement:
595
        case ts.SyntaxKind.PartiallyEmittedExpression:
596
            return hasSideEffects(node.expression, options);
597
        case ts.SyntaxKind.BinaryExpression:
598
            return isAssignmentKind(node.operatorToken.kind) ||
599
                hasSideEffects(node.left, options) ||
600
                hasSideEffects(node.right, options);
601
        case ts.SyntaxKind.PrefixUnaryExpression:
602
            switch (node.operator) {
603
                case ts.SyntaxKind.PlusPlusToken:
604
                case ts.SyntaxKind.MinusMinusToken:
605
                    return true;
606
                default:
607
                    return hasSideEffects(node.operand, options);
608
            }
609
        case ts.SyntaxKind.ElementAccessExpression:
610
            return hasSideEffects(node.expression, options) ||
611
                node.argumentExpression !== undefined &&
612
                    hasSideEffects(node.argumentExpression, options);
613
        case ts.SyntaxKind.ConditionalExpression:
614
            return hasSideEffects(node.condition, options) ||
615
                hasSideEffects(node.whenTrue, options) ||
616
                hasSideEffects(node.whenFalse, options);
617
        case ts.SyntaxKind.NewExpression:
618
            if (options & 2 || hasSideEffects(node.expression, options))
619
                return true;
620
            if (node.arguments !== undefined)
621
                for (const child of node.arguments)
622
                    if (hasSideEffects(child, options))
623
                        return true;
624
            return false;
625
        case ts.SyntaxKind.TaggedTemplateExpression:
626
            if (options & 1 || hasSideEffects(node.tag, options))
627
                return true;
628
            if (node.template.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)
629
                return false;
630
            node = node.template;
631
        case ts.SyntaxKind.TemplateExpression:
632
            for (const child of node.templateSpans)
633
                if (hasSideEffects(child.expression, options))
634
                    return true;
635
            return false;
636
        case ts.SyntaxKind.ClassExpression:
637
            return classExpressionHasSideEffects(node, options);
638
        case ts.SyntaxKind.ArrayLiteralExpression:
639
            for (const child of node.elements)
640
                if (hasSideEffects(child, options))
641
                    return true;
642
            return false;
643
        case ts.SyntaxKind.ObjectLiteralExpression:
644
            for (const child of node.properties) {
645
                if (child.name !== undefined && child.name.kind === ts.SyntaxKind.ComputedPropertyName &&
646
                    hasSideEffects(child.name.expression, options))
647
                    return true;
648
                switch (child.kind) {
649
                    case ts.SyntaxKind.PropertyAssignment:
650
                        if (hasSideEffects(child.initializer, options))
651
                            return true;
652
                        break;
653
                    case ts.SyntaxKind.SpreadAssignment:
654
                        if (hasSideEffects(child.expression, options))
655
                            return true;
656
                }
657
            }
658
            return false;
659
        case ts.SyntaxKind.JsxExpression:
660
            return node.expression !== undefined && hasSideEffects(node.expression, options);
661
        case ts.SyntaxKind.JsxElement:
662
        case ts.SyntaxKind.JsxFragment:
663
            for (const child of node.children)
664
                if (child.kind !== ts.SyntaxKind.JsxText && hasSideEffects(child, options))
665
                    return true;
666
            if (node.kind === ts.SyntaxKind.JsxFragment)
667
                return false;
668
            node = node.openingElement;
669
        case ts.SyntaxKind.JsxSelfClosingElement:
670
        case ts.SyntaxKind.JsxOpeningElement:
671
            if (options & 4)
672
                return true;
673
            for (const child of node.attributes.properties) {
674
                if (child.kind === ts.SyntaxKind.JsxSpreadAttribute) {
675
                    if (hasSideEffects(child.expression, options))
676
                        return true;
677
                }
678
                else if (child.initializer !== undefined && hasSideEffects(child.initializer, options)) {
679
                    return true;
680
                }
681
            }
682
            return false;
683
        case ts.SyntaxKind.CommaListExpression:
684
            for (const child of node.elements)
685
                if (hasSideEffects(child, options))
686
                    return true;
687
            return false;
688
        default:
689
            return false;
690
    }
691
}
692
exports.hasSideEffects = hasSideEffects;
693
function classExpressionHasSideEffects(node, options) {
694
    if (node.heritageClauses !== undefined && node.heritageClauses[0].token === ts.SyntaxKind.ExtendsKeyword)
695
        for (const base of node.heritageClauses[0].types)
696
            if (hasSideEffects(base.expression, options))
697
                return true;
698
    for (const child of node.members)
699
        if (child.name !== undefined && child.name.kind === ts.SyntaxKind.ComputedPropertyName &&
700
            hasSideEffects(child.name.expression, options) ||
701
            node_1.isPropertyDeclaration(child) && child.initializer !== undefined &&
702
                hasSideEffects(child.initializer, options))
703
            return true;
704
    return false;
705
}
706
function getDeclarationOfBindingElement(node) {
707
    let parent = node.parent.parent;
708
    while (parent.kind === ts.SyntaxKind.BindingElement)
709
        parent = parent.parent.parent;
710
    return parent;
711
}
712
exports.getDeclarationOfBindingElement = getDeclarationOfBindingElement;
713
function isExpressionValueUsed(node) {
714
    while (true) {
715
        const parent = node.parent;
716
        switch (parent.kind) {
717
            case ts.SyntaxKind.CallExpression:
718
            case ts.SyntaxKind.NewExpression:
719
            case ts.SyntaxKind.ElementAccessExpression:
720
            case ts.SyntaxKind.WhileStatement:
721
            case ts.SyntaxKind.DoStatement:
722
            case ts.SyntaxKind.WithStatement:
723
            case ts.SyntaxKind.ThrowStatement:
724
            case ts.SyntaxKind.ReturnStatement:
725
            case ts.SyntaxKind.JsxExpression:
726
            case ts.SyntaxKind.JsxSpreadAttribute:
727
            case ts.SyntaxKind.JsxElement:
728
            case ts.SyntaxKind.JsxFragment:
729
            case ts.SyntaxKind.JsxSelfClosingElement:
730
            case ts.SyntaxKind.ComputedPropertyName:
731
            case ts.SyntaxKind.ArrowFunction:
732
            case ts.SyntaxKind.ExportSpecifier:
733
            case ts.SyntaxKind.ExportAssignment:
734
            case ts.SyntaxKind.ImportDeclaration:
735
            case ts.SyntaxKind.ExternalModuleReference:
736
            case ts.SyntaxKind.Decorator:
737
            case ts.SyntaxKind.TaggedTemplateExpression:
738
            case ts.SyntaxKind.TemplateSpan:
739
            case ts.SyntaxKind.ExpressionWithTypeArguments:
740
            case ts.SyntaxKind.TypeOfExpression:
741
            case ts.SyntaxKind.AwaitExpression:
742
            case ts.SyntaxKind.YieldExpression:
743
            case ts.SyntaxKind.LiteralType:
744
            case ts.SyntaxKind.JsxAttributes:
745
            case ts.SyntaxKind.JsxOpeningElement:
746
            case ts.SyntaxKind.JsxClosingElement:
747
            case ts.SyntaxKind.IfStatement:
748
            case ts.SyntaxKind.CaseClause:
749
            case ts.SyntaxKind.SwitchStatement:
750
                return true;
751
            case ts.SyntaxKind.PropertyAccessExpression:
752
                return parent.expression === node;
753
            case ts.SyntaxKind.QualifiedName:
754
                return parent.left === node;
755
            case ts.SyntaxKind.ShorthandPropertyAssignment:
756
                return parent.objectAssignmentInitializer === node ||
757
                    !isInDestructuringAssignment(parent);
758
            case ts.SyntaxKind.PropertyAssignment:
759
                return parent.initializer === node && !isInDestructuringAssignment(parent);
760
            case ts.SyntaxKind.SpreadAssignment:
761
            case ts.SyntaxKind.SpreadElement:
762
            case ts.SyntaxKind.ArrayLiteralExpression:
763
                return !isInDestructuringAssignment(parent);
764
            case ts.SyntaxKind.ParenthesizedExpression:
765
            case ts.SyntaxKind.AsExpression:
766
            case ts.SyntaxKind.TypeAssertionExpression:
767
            case ts.SyntaxKind.PostfixUnaryExpression:
768
            case ts.SyntaxKind.PrefixUnaryExpression:
769
            case ts.SyntaxKind.NonNullExpression:
770
                node = parent;
771
                break;
772
            case ts.SyntaxKind.ForStatement:
773
                return parent.condition === node;
774
            case ts.SyntaxKind.ForInStatement:
775
            case ts.SyntaxKind.ForOfStatement:
776
                return parent.expression === node;
777
            case ts.SyntaxKind.ConditionalExpression:
778
                if (parent.condition === node)
779
                    return true;
780
                node = parent;
781
                break;
782
            case ts.SyntaxKind.PropertyDeclaration:
783
            case ts.SyntaxKind.BindingElement:
784
            case ts.SyntaxKind.VariableDeclaration:
785
            case ts.SyntaxKind.Parameter:
786
            case ts.SyntaxKind.EnumMember:
787
                return parent.initializer === node;
788
            case ts.SyntaxKind.ImportEqualsDeclaration:
789
                return parent.moduleReference === node;
790
            case ts.SyntaxKind.CommaListExpression:
791
                if (parent.elements[parent.elements.length - 1] !== node)
792
                    return false;
793
                node = parent;
794
                break;
795
            case ts.SyntaxKind.BinaryExpression:
796
                if (parent.right === node) {
797
                    if (parent.operatorToken.kind === ts.SyntaxKind.CommaToken) {
798
                        node = parent;
799
                        break;
800
                    }
801
                    return true;
802
                }
803
                switch (parent.operatorToken.kind) {
804
                    case ts.SyntaxKind.CommaToken:
805
                    case ts.SyntaxKind.EqualsToken:
806
                        return false;
807
                    case ts.SyntaxKind.EqualsEqualsEqualsToken:
808
                    case ts.SyntaxKind.EqualsEqualsToken:
809
                    case ts.SyntaxKind.ExclamationEqualsEqualsToken:
810
                    case ts.SyntaxKind.ExclamationEqualsToken:
811
                    case ts.SyntaxKind.InstanceOfKeyword:
812
                    case ts.SyntaxKind.PlusToken:
813
                    case ts.SyntaxKind.MinusToken:
814
                    case ts.SyntaxKind.AsteriskToken:
815
                    case ts.SyntaxKind.SlashToken:
816
                    case ts.SyntaxKind.PercentToken:
817
                    case ts.SyntaxKind.AsteriskAsteriskToken:
818
                    case ts.SyntaxKind.GreaterThanToken:
819
                    case ts.SyntaxKind.GreaterThanGreaterThanToken:
820
                    case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
821
                    case ts.SyntaxKind.GreaterThanEqualsToken:
822
                    case ts.SyntaxKind.LessThanToken:
823
                    case ts.SyntaxKind.LessThanLessThanToken:
824
                    case ts.SyntaxKind.LessThanEqualsToken:
825
                    case ts.SyntaxKind.AmpersandToken:
826
                    case ts.SyntaxKind.BarToken:
827
                    case ts.SyntaxKind.CaretToken:
828
                    case ts.SyntaxKind.BarBarToken:
829
                    case ts.SyntaxKind.AmpersandAmpersandToken:
830
                    case ts.SyntaxKind.InKeyword:
831
                        return true;
832
                    default:
833
                        node = parent;
834
                }
835
                break;
836
            default:
837
                return false;
838
        }
839
    }
840
}
841
exports.isExpressionValueUsed = isExpressionValueUsed;
842
function isInDestructuringAssignment(node) {
843
    switch (node.kind) {
844
        case ts.SyntaxKind.ShorthandPropertyAssignment:
845
            if (node.objectAssignmentInitializer !== undefined)
846
                return true;
847
        case ts.SyntaxKind.PropertyAssignment:
848
        case ts.SyntaxKind.SpreadAssignment:
849
            node = node.parent;
850
            break;
851
        case ts.SyntaxKind.SpreadElement:
852
            if (node.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
853
                return false;
854
            node = node.parent;
855
    }
856
    while (true) {
857
        switch (node.parent.kind) {
858
            case ts.SyntaxKind.BinaryExpression:
859
                return node.parent.left === node &&
860
                    node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
861
            case ts.SyntaxKind.ForOfStatement:
862
                return node.parent.initializer === node;
863
            case ts.SyntaxKind.ArrayLiteralExpression:
864
            case ts.SyntaxKind.ObjectLiteralExpression:
865
                node = node.parent;
866
                break;
867
            case ts.SyntaxKind.SpreadAssignment:
868
            case ts.SyntaxKind.PropertyAssignment:
869
                node = node.parent.parent;
870
                break;
871
            case ts.SyntaxKind.SpreadElement:
872
                if (node.parent.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
873
                    return false;
874
                node = node.parent.parent;
875
                break;
876
            default:
877
                return false;
878
        }
879
    }
880
}
881
var AccessKind;
882
(function (AccessKind) {
883
    AccessKind[AccessKind["None"] = 0] = "None";
884
    AccessKind[AccessKind["Read"] = 1] = "Read";
885
    AccessKind[AccessKind["Write"] = 2] = "Write";
886
    AccessKind[AccessKind["Delete"] = 4] = "Delete";
887
    AccessKind[AccessKind["ReadWrite"] = 3] = "ReadWrite";
888
    AccessKind[AccessKind["Modification"] = 6] = "Modification";
889
})(AccessKind = exports.AccessKind || (exports.AccessKind = {}));
890
function getAccessKind(node) {
891
    const parent = node.parent;
892
    switch (parent.kind) {
893
        case ts.SyntaxKind.DeleteExpression:
894
            return 4;
895
        case ts.SyntaxKind.PostfixUnaryExpression:
896
            return 3;
897
        case ts.SyntaxKind.PrefixUnaryExpression:
898
            return parent.operator === ts.SyntaxKind.PlusPlusToken ||
899
                parent.operator === ts.SyntaxKind.MinusMinusToken
900
                ? 3
901
                : 1;
902
        case ts.SyntaxKind.BinaryExpression:
903
            return parent.right === node
904
                ? 1
905
                : !isAssignmentKind(parent.operatorToken.kind)
906
                    ? 1
907
                    : parent.operatorToken.kind === ts.SyntaxKind.EqualsToken
908
                        ? 2
909
                        : 3;
910
        case ts.SyntaxKind.ShorthandPropertyAssignment:
911
            return parent.objectAssignmentInitializer === node
912
                ? 1
913
                : isInDestructuringAssignment(parent)
914
                    ? 2
915
                    : 1;
916
        case ts.SyntaxKind.PropertyAssignment:
917
            return parent.name === node
918
                ? 0
919
                : isInDestructuringAssignment(parent)
920
                    ? 2
921
                    : 1;
922
        case ts.SyntaxKind.ArrayLiteralExpression:
923
        case ts.SyntaxKind.SpreadElement:
924
        case ts.SyntaxKind.SpreadAssignment:
925
            return isInDestructuringAssignment(parent)
926
                ? 2
927
                : 1;
928
        case ts.SyntaxKind.ParenthesizedExpression:
929
        case ts.SyntaxKind.NonNullExpression:
930
        case ts.SyntaxKind.TypeAssertionExpression:
931
        case ts.SyntaxKind.AsExpression:
932
            return getAccessKind(parent);
933
        case ts.SyntaxKind.ForOfStatement:
934
        case ts.SyntaxKind.ForInStatement:
935
            return parent.initializer === node
936
                ? 2
937
                : 1;
938
        case ts.SyntaxKind.ExpressionWithTypeArguments:
939
            return parent.parent.token === ts.SyntaxKind.ExtendsKeyword &&
940
                parent.parent.parent.kind !== ts.SyntaxKind.InterfaceDeclaration
941
                ? 1
942
                : 0;
943
        case ts.SyntaxKind.ComputedPropertyName:
944
        case ts.SyntaxKind.ExpressionStatement:
945
        case ts.SyntaxKind.TypeOfExpression:
946
        case ts.SyntaxKind.ElementAccessExpression:
947
        case ts.SyntaxKind.ForStatement:
948
        case ts.SyntaxKind.IfStatement:
949
        case ts.SyntaxKind.DoStatement:
950
        case ts.SyntaxKind.WhileStatement:
951
        case ts.SyntaxKind.SwitchStatement:
952
        case ts.SyntaxKind.WithStatement:
953
        case ts.SyntaxKind.ThrowStatement:
954
        case ts.SyntaxKind.CallExpression:
955
        case ts.SyntaxKind.NewExpression:
956
        case ts.SyntaxKind.TaggedTemplateExpression:
957
        case ts.SyntaxKind.JsxExpression:
958
        case ts.SyntaxKind.Decorator:
959
        case ts.SyntaxKind.TemplateSpan:
960
        case ts.SyntaxKind.JsxOpeningElement:
961
        case ts.SyntaxKind.JsxSelfClosingElement:
962
        case ts.SyntaxKind.JsxSpreadAttribute:
963
        case ts.SyntaxKind.VoidExpression:
964
        case ts.SyntaxKind.ReturnStatement:
965
        case ts.SyntaxKind.AwaitExpression:
966
        case ts.SyntaxKind.YieldExpression:
967
        case ts.SyntaxKind.ConditionalExpression:
968
        case ts.SyntaxKind.CaseClause:
969
        case ts.SyntaxKind.JsxElement:
970
            return 1;
971
        case ts.SyntaxKind.ArrowFunction:
972
            return parent.body === node
973
                ? 1
974
                : 2;
975
        case ts.SyntaxKind.PropertyDeclaration:
976
        case ts.SyntaxKind.VariableDeclaration:
977
        case ts.SyntaxKind.Parameter:
978
        case ts.SyntaxKind.EnumMember:
979
        case ts.SyntaxKind.BindingElement:
980
        case ts.SyntaxKind.JsxAttribute:
981
            return parent.initializer === node
982
                ? 1
983
                : 0;
984
        case ts.SyntaxKind.PropertyAccessExpression:
985
            return parent.expression === node
986
                ? 1
987
                : 0;
988
        case ts.SyntaxKind.ExportAssignment:
989
            return parent.isExportEquals
990
                ? 1
991
                : 0;
992
    }
993
    return 0;
994
}
995
exports.getAccessKind = getAccessKind;
996
function isReassignmentTarget(node) {
997
    return (getAccessKind(node) & 2) !== 0;
998
}
999
exports.isReassignmentTarget = isReassignmentTarget;
1000
function canHaveJsDoc(node) {
1001
    const kind = node.kind;
1002
    switch (kind) {
1003
        case ts.SyntaxKind.Parameter:
1004
        case ts.SyntaxKind.CallSignature:
1005
        case ts.SyntaxKind.ConstructSignature:
1006
        case ts.SyntaxKind.MethodSignature:
1007
        case ts.SyntaxKind.PropertySignature:
1008
        case ts.SyntaxKind.ArrowFunction:
1009
        case ts.SyntaxKind.ParenthesizedExpression:
1010
        case ts.SyntaxKind.SpreadAssignment:
1011
        case ts.SyntaxKind.ShorthandPropertyAssignment:
1012
        case ts.SyntaxKind.PropertyAssignment:
1013
        case ts.SyntaxKind.FunctionExpression:
1014
        case ts.SyntaxKind.FunctionDeclaration:
1015
        case ts.SyntaxKind.LabeledStatement:
1016
        case ts.SyntaxKind.ExpressionStatement:
1017
        case ts.SyntaxKind.VariableStatement:
1018
        case ts.SyntaxKind.Constructor:
1019
        case ts.SyntaxKind.MethodDeclaration:
1020
        case ts.SyntaxKind.PropertyDeclaration:
1021
        case ts.SyntaxKind.GetAccessor:
1022
        case ts.SyntaxKind.SetAccessor:
1023
        case ts.SyntaxKind.ClassDeclaration:
1024
        case ts.SyntaxKind.ClassExpression:
1025
        case ts.SyntaxKind.InterfaceDeclaration:
1026
        case ts.SyntaxKind.TypeAliasDeclaration:
1027
        case ts.SyntaxKind.EnumMember:
1028
        case ts.SyntaxKind.EnumDeclaration:
1029
        case ts.SyntaxKind.ModuleDeclaration:
1030
        case ts.SyntaxKind.ImportEqualsDeclaration:
1031
        case ts.SyntaxKind.IndexSignature:
1032
        case ts.SyntaxKind.FunctionType:
1033
        case ts.SyntaxKind.ConstructorType:
1034
        case ts.SyntaxKind.JSDocFunctionType:
1035
        case ts.SyntaxKind.EndOfFileToken:
1036
        case ts.SyntaxKind.ExportDeclaration:
1037
            return true;
1038
        default:
1039
            return false;
1040
    }
1041
}
1042
exports.canHaveJsDoc = canHaveJsDoc;
1043
function getJsDoc(node, sourceFile) {
1044
    if (node.kind === ts.SyntaxKind.EndOfFileToken)
1045
        return parseJsDocWorker(node, sourceFile || node.parent);
1046
    const result = [];
1047
    for (const child of node.getChildren(sourceFile)) {
1048
        if (!node_1.isJsDoc(child))
1049
            break;
1050
        result.push(child);
1051
    }
1052
    return result;
1053
}
1054
exports.getJsDoc = getJsDoc;
1055
function parseJsDocOfNode(node, considerTrailingComments, sourceFile = node.getSourceFile()) {
1056
    if (canHaveJsDoc(node) && node.kind !== ts.SyntaxKind.EndOfFileToken) {
1057
        const result = getJsDoc(node, sourceFile);
1058
        if (result.length !== 0 || !considerTrailingComments)
1059
            return result;
1060
    }
1061
    return parseJsDocWorker(node, sourceFile, considerTrailingComments);
1062
}
1063
exports.parseJsDocOfNode = parseJsDocOfNode;
1064
function parseJsDocWorker(node, sourceFile, considerTrailingComments) {
1065
    const nodeStart = node.getStart(sourceFile);
1066
    const start = ts[considerTrailingComments && isSameLine(sourceFile, node.pos, nodeStart)
1067
        ? 'forEachTrailingCommentRange'
1068
        : 'forEachLeadingCommentRange'](sourceFile.text, node.pos, (pos, _end, kind) => kind === ts.SyntaxKind.MultiLineCommentTrivia && sourceFile.text[pos + 2] === '*' ? { pos } : undefined);
1069
    if (start === undefined)
1070
        return [];
1071
    const startPos = start.pos;
1072
    const text = sourceFile.text.slice(startPos, nodeStart);
1073
    const newSourceFile = ts.createSourceFile('jsdoc.ts', `${text}var a;`, sourceFile.languageVersion);
1074
    const result = getJsDoc(newSourceFile.statements[0], newSourceFile);
1075
    for (const doc of result)
1076
        updateNode(doc, node);
1077
    return result;
1078
    function updateNode(n, parent) {
1079
        n.pos += startPos;
1080
        n.end += startPos;
1081
        n.parent = parent;
1082
        return ts.forEachChild(n, (child) => updateNode(child, n), (children) => {
1083
            children.pos += startPos;
1084
            children.end += startPos;
1085
            for (const child of children)
1086
                updateNode(child, n);
1087
        });
1088
    }
1089
}
1090
var ImportKind;
1091
(function (ImportKind) {
1092
    ImportKind[ImportKind["ImportDeclaration"] = 1] = "ImportDeclaration";
1093
    ImportKind[ImportKind["ImportEquals"] = 2] = "ImportEquals";
1094
    ImportKind[ImportKind["ExportFrom"] = 4] = "ExportFrom";
1095
    ImportKind[ImportKind["DynamicImport"] = 8] = "DynamicImport";
1096
    ImportKind[ImportKind["Require"] = 16] = "Require";
1097
    ImportKind[ImportKind["ImportType"] = 32] = "ImportType";
1098
    ImportKind[ImportKind["All"] = 63] = "All";
1099
    ImportKind[ImportKind["AllImports"] = 59] = "AllImports";
1100
    ImportKind[ImportKind["AllStaticImports"] = 3] = "AllStaticImports";
1101
    ImportKind[ImportKind["AllImportExpressions"] = 24] = "AllImportExpressions";
1102
    ImportKind[ImportKind["AllRequireLike"] = 18] = "AllRequireLike";
1103
    ImportKind[ImportKind["AllNestedImports"] = 56] = "AllNestedImports";
1104
    ImportKind[ImportKind["AllTopLevelImports"] = 7] = "AllTopLevelImports";
1105
})(ImportKind = exports.ImportKind || (exports.ImportKind = {}));
1106
function findImports(sourceFile, kinds) {
1107
    const result = [];
1108
    for (const node of findImportLikeNodes(sourceFile, kinds)) {
1109
        switch (node.kind) {
1110
            case ts.SyntaxKind.ImportDeclaration:
1111
                addIfTextualLiteral(node.moduleSpecifier);
1112
                break;
1113
            case ts.SyntaxKind.ImportEqualsDeclaration:
1114
                addIfTextualLiteral(node.moduleReference.expression);
1115
                break;
1116
            case ts.SyntaxKind.ExportDeclaration:
1117
                addIfTextualLiteral(node.moduleSpecifier);
1118
                break;
1119
            case ts.SyntaxKind.CallExpression:
1120
                addIfTextualLiteral(node.arguments[0]);
1121
                break;
1122
            case ts.SyntaxKind.ImportType:
1123
                if (node_1.isLiteralTypeNode(node.argument))
1124
                    addIfTextualLiteral(node.argument.literal);
1125
                break;
1126
            default:
1127
                throw new Error('unexpected node');
1128
        }
1129
    }
1130
    return result;
1131
    function addIfTextualLiteral(node) {
1132
        if (node_1.isTextualLiteral(node))
1133
            result.push(node);
1134
    }
1135
}
1136
exports.findImports = findImports;
1137
function findImportLikeNodes(sourceFile, kinds) {
1138
    return new ImportFinder(sourceFile, kinds).find();
1139
}
1140
exports.findImportLikeNodes = findImportLikeNodes;
1141
class ImportFinder {
1142
    constructor(_sourceFile, _options) {
1143
        this._sourceFile = _sourceFile;
1144
        this._options = _options;
1145
        this._result = [];
1146
    }
1147
    find() {
1148
        if (this._sourceFile.isDeclarationFile)
1149
            this._options &= ~24;
1150
        if (this._options & 7)
1151
            this._findImports(this._sourceFile.statements);
1152
        if (this._options & 56)
1153
            this._findNestedImports();
1154
        return this._result;
1155
    }
1156
    _findImports(statements) {
1157
        for (const statement of statements) {
1158
            if (node_1.isImportDeclaration(statement)) {
1159
                if (this._options & 1)
1160
                    this._result.push(statement);
1161
            }
1162
            else if (node_1.isImportEqualsDeclaration(statement)) {
1163
                if (this._options & 2 &&
1164
                    statement.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference)
1165
                    this._result.push(statement);
1166
            }
1167
            else if (node_1.isExportDeclaration(statement)) {
1168
                if (statement.moduleSpecifier !== undefined && this._options & 4)
1169
                    this._result.push(statement);
1170
            }
1171
            else if (node_1.isModuleDeclaration(statement)) {
1172
                this._findImportsInModule(statement);
1173
            }
1174
        }
1175
    }
1176
    _findImportsInModule(declaration) {
1177
        if (declaration.body === undefined)
1178
            return;
1179
        if (declaration.body.kind === ts.SyntaxKind.ModuleDeclaration)
1180
            return this._findImportsInModule(declaration.body);
1181
        this._findImports(declaration.body.statements);
1182
    }
1183
    _findNestedImports() {
1184
        let re;
1185
        if ((this._options & 56) === 16) {
1186
            re = /\brequire\s*[</(]/g;
1187
        }
1188
        else if (this._options & 16) {
1189
            re = /\b(?:import|require)\s*[</(]/g;
1190
        }
1191
        else {
1192
            re = /\bimport\s*[</(]/g;
1193
        }
1194
        const isJavaScriptFile = (this._sourceFile.flags & ts.NodeFlags.JavaScriptFile) !== 0;
1195
        for (let match = re.exec(this._sourceFile.text); match !== null; match = re.exec(this._sourceFile.text)) {
1196
            const token = getTokenAtPositionWorker(this._sourceFile, match.index, this._sourceFile, match[0][0] === 'i' && isJavaScriptFile);
1197
            if (token.kind === ts.SyntaxKind.ImportKeyword) {
1198
                if (token.end - 'import'.length !== match.index)
1199
                    continue;
1200
                switch (token.parent.kind) {
1201
                    case ts.SyntaxKind.ImportType:
1202
                        this._result.push(token.parent);
1203
                        break;
1204
                    case ts.SyntaxKind.CallExpression:
1205
                        if (token.parent.arguments.length === 1)
1206
                            this._result.push(token.parent);
1207
                }
1208
            }
1209
            else if (token.kind === ts.SyntaxKind.Identifier &&
1210
                token.end - 'require'.length === match.index &&
1211
                token.parent.kind === ts.SyntaxKind.CallExpression &&
1212
                token.parent.expression === token &&
1213
                token.parent.arguments.length === 1) {
1214
                this._result.push(token.parent);
1215
            }
1216
        }
1217
    }
1218
}
1219
function isStatementInAmbientContext(node) {
1220
    while (node.flags & ts.NodeFlags.NestedNamespace)
1221
        node = node.parent;
1222
    return hasModifier(node.modifiers, ts.SyntaxKind.DeclareKeyword) || isAmbientModuleBlock(node.parent);
1223
}
1224
exports.isStatementInAmbientContext = isStatementInAmbientContext;
1225
function isAmbientModuleBlock(node) {
1226
    while (node.kind === ts.SyntaxKind.ModuleBlock) {
1227
        do
1228
            node = node.parent;
1229
        while (node.flags & ts.NodeFlags.NestedNamespace);
1230
        if (hasModifier(node.modifiers, ts.SyntaxKind.DeclareKeyword))
1231
            return true;
1232
        node = node.parent;
1233
    }
1234
    return false;
1235
}
1236
exports.isAmbientModuleBlock = isAmbientModuleBlock;
1237
function getIIFE(func) {
1238
    let node = func.parent;
1239
    while (node.kind === ts.SyntaxKind.ParenthesizedExpression)
1240
        node = node.parent;
1241
    return node_1.isCallExpression(node) && func.end <= node.expression.end ? node : undefined;
1242
}
1243
exports.getIIFE = getIIFE;
1244
function isStrictCompilerOptionEnabled(options, option) {
1245
    return (options.strict ? options[option] !== false : options[option] === true) &&
1246
        (option !== 'strictPropertyInitialization' || isStrictCompilerOptionEnabled(options, 'strictNullChecks'));
1247
}
1248
exports.isStrictCompilerOptionEnabled = isStrictCompilerOptionEnabled;
1249
function isCompilerOptionEnabled(options, option) {
1250
    switch (option) {
1251
        case 'stripInternal':
1252
            return options.stripInternal === true && isCompilerOptionEnabled(options, 'declaration');
1253
        case 'declaration':
1254
            return options.declaration || isCompilerOptionEnabled(options, 'composite');
1255
        case 'incremental':
1256
            return options.incremental === undefined ? isCompilerOptionEnabled(options, 'composite') : options.incremental;
1257
        case 'skipDefaultLibCheck':
1258
            return options.skipDefaultLibCheck || isCompilerOptionEnabled(options, 'skipLibCheck');
1259
        case 'suppressImplicitAnyIndexErrors':
1260
            return options.suppressImplicitAnyIndexErrors === true && isCompilerOptionEnabled(options, 'noImplicitAny');
1261
        case 'allowSyntheticDefaultImports':
1262
            return options.allowSyntheticDefaultImports !== undefined
1263
                ? options.allowSyntheticDefaultImports
1264
                : isCompilerOptionEnabled(options, 'esModuleInterop') || options.module === ts.ModuleKind.System;
1265
        case 'noImplicitAny':
1266
        case 'noImplicitThis':
1267
        case 'strictNullChecks':
1268
        case 'strictFunctionTypes':
1269
        case 'strictPropertyInitialization':
1270
        case 'alwaysStrict':
1271
        case 'strictBindCallApply':
1272
            return isStrictCompilerOptionEnabled(options, option);
1273
    }
1274
    return options[option] === true;
1275
}
1276
exports.isCompilerOptionEnabled = isCompilerOptionEnabled;
1277
function isAmbientModule(node) {
1278
    return node.name.kind === ts.SyntaxKind.StringLiteral || (node.flags & ts.NodeFlags.GlobalAugmentation) !== 0;
1279
}
1280
exports.isAmbientModule = isAmbientModule;
1281
function getCheckJsDirective(source) {
1282
    let directive;
1283
    ts.forEachLeadingCommentRange(source, (ts.getShebang(source) || '').length, (pos, end, kind) => {
1284
        if (kind === ts.SyntaxKind.SingleLineCommentTrivia) {
1285
            const text = source.slice(pos, end);
1286
            const match = /^\/{2,3}\s*@ts-(no)?check(?:\s|$)/i.exec(text);
1287
            if (match !== null)
1288
                directive = { pos, end, enabled: match[1] === undefined };
1289
        }
1290
    });
1291
    return directive;
1292
}
1293
exports.getCheckJsDirective = getCheckJsDirective;
1294
function isConstAssertion(node) {
1295
    return node_1.isTypeReferenceNode(node.type) &&
1296
        node.type.typeName.kind === ts.SyntaxKind.Identifier &&
1297
        node.type.typeName.escapedText === 'const';
1298
}
1299
exports.isConstAssertion = isConstAssertion;
1300
function isInConstContext(node) {
1301
    let current = node;
1302
    while (true) {
1303
        const parent = current.parent;
1304
        outer: switch (parent.kind) {
1305
            case ts.SyntaxKind.TypeAssertionExpression:
1306
            case ts.SyntaxKind.AsExpression:
1307
                return isConstAssertion(parent);
1308
            case ts.SyntaxKind.PrefixUnaryExpression:
1309
                if (current.kind !== ts.SyntaxKind.NumericLiteral)
1310
                    return false;
1311
                switch (parent.operator) {
1312
                    case ts.SyntaxKind.PlusToken:
1313
                    case ts.SyntaxKind.MinusToken:
1314
                        current = parent;
1315
                        break outer;
1316
                    default:
1317
                        return false;
1318
                }
1319
            case ts.SyntaxKind.PropertyAssignment:
1320
                if (parent.initializer !== current)
1321
                    return false;
1322
                current = parent.parent;
1323
                break;
1324
            case ts.SyntaxKind.ShorthandPropertyAssignment:
1325
                current = parent.parent;
1326
                break;
1327
            case ts.SyntaxKind.ParenthesizedExpression:
1328
            case ts.SyntaxKind.ArrayLiteralExpression:
1329
            case ts.SyntaxKind.ObjectLiteralExpression:
1330
                current = parent;
1331
                break;
1332
            default:
1333
                return false;
1334
        }
1335
    }
1336
}
1337
exports.isInConstContext = isInConstContext;
1338
function isReadonlyAssignmentDeclaration(node, checker) {
1339
    if (!isBindableObjectDefinePropertyCall(node))
1340
        return false;
1341
    const descriptorType = checker.getTypeAtLocation(node.arguments[2]);
1342
    if (descriptorType.getProperty('value') === undefined)
1343
        return descriptorType.getProperty('set') === undefined;
1344
    const writableProp = descriptorType.getProperty('writable');
1345
    if (writableProp === undefined)
1346
        return false;
1347
    const writableType = writableProp.valueDeclaration !== undefined && node_1.isPropertyAssignment(writableProp.valueDeclaration)
1348
        ? checker.getTypeAtLocation(writableProp.valueDeclaration.initializer)
1349
        : checker.getTypeOfSymbolAtLocation(writableProp, node.arguments[2]);
1350
    return type_1.isBooleanLiteralType(writableType, false);
1351
}
1352
exports.isReadonlyAssignmentDeclaration = isReadonlyAssignmentDeclaration;
1353
function isBindableObjectDefinePropertyCall(node) {
1354
    return node.arguments.length === 3 &&
1355
        node_1.isEntityNameExpression(node.arguments[0]) &&
1356
        node_1.isNumericOrStringLikeLiteral(node.arguments[1]) &&
1357
        node_1.isPropertyAccessExpression(node.expression) &&
1358
        node.expression.name.escapedText === 'defineProperty' &&
1359
        node_1.isIdentifier(node.expression.expression) &&
1360
        node.expression.expression.escapedText === 'Object';
1361
}
1362
exports.isBindableObjectDefinePropertyCall = isBindableObjectDefinePropertyCall;
1363
function isWellKnownSymbolLiterally(node) {
1364
    return ts.isPropertyAccessExpression(node) &&
1365
        ts.isIdentifier(node.expression) &&
1366
        node.expression.escapedText === 'Symbol';
1367
}
1368
exports.isWellKnownSymbolLiterally = isWellKnownSymbolLiterally;
1369
function getPropertyNameOfWellKnownSymbol(node) {
1370
    return {
1371
        displayName: `[Symbol.${node.name.text}]`,
1372
        symbolName: ('__@' + node.name.text),
1373
    };
1374
}
1375
exports.getPropertyNameOfWellKnownSymbol = getPropertyNameOfWellKnownSymbol;
1376
function getLateBoundPropertyNames(node, checker) {
1377
    const result = {
1378
        known: true,
1379
        names: [],
1380
    };
1381
    node = unwrapParentheses(node);
1382
    if (isWellKnownSymbolLiterally(node)) {
1383
        result.names.push(getPropertyNameOfWellKnownSymbol(node));
1384
    }
1385
    else {
1386
        const type = checker.getTypeAtLocation(node);
1387
        for (const key of type_1.unionTypeParts(checker.getBaseConstraintOfType(type) || type)) {
1388
            const propertyName = type_1.getPropertyNameFromType(key);
1389
            if (propertyName) {
1390
                result.names.push(propertyName);
1391
            }
1392
            else {
1393
                result.known = false;
1394
            }
1395
        }
1396
    }
1397
    return result;
1398
}
1399
exports.getLateBoundPropertyNames = getLateBoundPropertyNames;
1400
function getLateBoundPropertyNamesOfPropertyName(node, checker) {
1401
    const staticName = getPropertyName(node);
1402
    return staticName !== undefined
1403
        ? { known: true, names: [{ displayName: staticName, symbolName: ts.escapeLeadingUnderscores(staticName) }] }
1404
        : getLateBoundPropertyNames(node.expression, checker);
1405
}
1406
exports.getLateBoundPropertyNamesOfPropertyName = getLateBoundPropertyNamesOfPropertyName;
1407
function getSingleLateBoundPropertyNameOfPropertyName(node, checker) {
1408
    const staticName = getPropertyName(node);
1409
    if (staticName !== undefined)
1410
        return { displayName: staticName, symbolName: ts.escapeLeadingUnderscores(staticName) };
1411
    const { expression } = node;
1412
    return isWellKnownSymbolLiterally(expression)
1413
        ? getPropertyNameOfWellKnownSymbol(expression)
1414
        : type_1.getPropertyNameFromType(checker.getTypeAtLocation(expression));
1415
}
1416
exports.getSingleLateBoundPropertyNameOfPropertyName = getSingleLateBoundPropertyNameOfPropertyName;
1417
function unwrapParentheses(node) {
1418
    while (node.kind === ts.SyntaxKind.ParenthesizedExpression)
1419
        node = node.expression;
1420
    return node;
1421
}
1422
exports.unwrapParentheses = unwrapParentheses;
1423